//
//  HACLineChartView.m
//  HStockCharts
//
//  Created by Hotacool on 2018/1/3.
//

#import "HACLineChartView.h"
#import "HACLineChartDataSet.h"
#import "HACPointEntry.h"

static const CGFloat axisLabelWidth = 40;
@interface HACLineChartView ()
/** 点数据 */
@property (nonatomic, strong) NSMutableDictionary <NSNumber*, NSArray<HACPointEntry*>*> *lineDicData;
/** 画线点数据 */
@property (nonatomic, strong) NSMutableArray *lineDrawingData;
@end
@implementation HACLineChartView {
    CGFloat _labelHeight;
}

- (void)dealloc {
}

- (void)setUp {
    [super setUp];
    // 初始化页面属性
    self.backgroundColor = [UIColor clearColor];
    self.autoresizingMask = UIViewAutoresizingFlexibleWidth;
    self.yAxisCount = 2;
    self.singleWidth = 1;
    self.visualCount = 60;
    self.pointRect = CGRectZero;
    
    _lineRenderer = [[HACLineRenderer alloc] initWithDataProvider:self];
    self.rightAxis.enable = NO;
    self.animator = [[HACAnimator alloc] init];
    self.animator.delegate = self;
}

- (void)setData:(HACChartData *)data {
    if (!data) {
        return;
    }
    _lineDicData = [NSMutableDictionary dictionary];
    _lineDrawingData = [NSMutableArray array];
    int index = 0, maxCount = 0;
    for (HACLineChartDataSet *dataSet in data.dataSets) {
        if ([dataSet isKindOfClass:[HACLineChartDataSet class]]) {
            HACLineComponents *lineItem = [[HACLineComponents alloc] init];
            lineItem.isCurve = dataSet.cubicEnabled;
            lineItem.lineColor = dataSet.lineColor;
            lineItem.fillColor = dataSet.fillColor;
            lineItem.isGradient = dataSet.gradientEnabled;
            lineItem.index = index;
            lineItem.lineBolder = dataSet.lineWidth>1?dataSet.lineWidth:1;
            [_lineDrawingData addObject:lineItem];
            NSArray *points = dataSet.values;
            if (points) {
                [_lineDicData setObject:points forKey:@(index)];
            }
            int tmpMax = (int)(points?points.count:0);
            if (tmpMax > maxCount) {
                maxCount = tmpMax;
            }
            index++;
        }
    }
    self.startIndex = 0;
    self.endIndex = MAX(0, (NSInteger)maxCount - 1);
    self.visualCount = (NSInteger)maxCount;
    [super setData:data];
}

- (NSInteger)actualCount {
    return self.endIndex - self.startIndex + 1;
}

- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];
    CGContextRef context = UIGraphicsGetCurrentContext();
    [self.lineRenderer drawInRect:rect context:context];
}

#pragma mark - provider protocol
- (NSArray *)lineDatasInRect:(CGRect)rect {
    if (!self.data)
        return nil;
    
    int index = 0;
    for (HACLineComponents *lineItem in self.lineDrawingData) {
        NSArray *points = _lineDicData[@(index)];
        if (!points) {
            continue;
        }
        lineItem.pointCount = (self.endIndex - self.startIndex) + 1;
        NSMutableArray *pointsArray = [NSMutableArray array];
        
        long len = self.endIndex - self.startIndex + 1;
        int phaseEnd = MIN(self.actualCount, len)*self.animator.phaseX;//动画
        for (NSInteger i = self.startIndex; i <= self.endIndex && i < self.actualCount; i++) {
            if (i >= phaseEnd || i >= points.count) {
                break;
            }
            id pointData = points[i];
            CGFloat x = 0.0, y = 0.0;
            x = [self xPointForIndex:i inRect:self.pointRect];
//            if (self.singleWidth > 0) {
//                // 如果已经绘制rect，需要偏移1/2 singleWidth实现居中
//                x += self.singleWidth / 2;
//            }
            CGFloat value = [self lineValueForItem:pointData lineIndex:lineItem.index];
            y = [self calculatorYForValue:value min:self.minValue max:self.maxValue inRect:self.pointRect];
            [pointsArray addObject:NSStringFromCGPoint(CGPointMake(x, y))];
        }
        lineItem.pointArray = pointsArray;
        index++;
    }
    return self.lineDrawingData;
}

- (CGFloat)lineValueForItem:(HACPointEntry *)data lineIndex:(NSInteger)index {
    return data.y;
}

// 计算最大，最小值
- (void)calculateLimitValue {
    CGFloat __block max = FLT_MIN;
    CGFloat __block min = FLT_MAX;
    
    [_lineDicData enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull key, NSArray<HACPointEntry *> * _Nonnull obj, BOOL * _Nonnull stop) {
        for (HACPointEntry *p in obj) {
            if (p.y > max) {
                max = p.y;
            }
            if (p.y < min) {
                min = p.y;
            }
        }
    }];
    self.maxValue = (max == FLT_MIN) ? .0 : max;
    self.minValue = (min == FLT_MAX) ? .0 : min;
    // axis custom setting
    if (self.leftAxis.customAxisMin) {
        self.minValue = self.leftAxis.axisMinimum;
    }
    CGFloat w = ABS(self.maxValue - self.minValue);
    if (self.leftAxis.spaceTop > 0) {
        self.maxValue += self.leftAxis.spaceTop*w;
    }
    if (self.leftAxis.spaceBottom > 0 && !self.leftAxis.customAxisMin) {
        self.minValue -= w*self.leftAxis.spaceBottom;
    }
}

- (NSString *)stringForAxisTextItem:(HACAxisComponents *)axisItem {
    return nil;
}

#pragma mark -- api
- (NSUInteger)indexAtChartForCoordinate:(CGPoint)point {
    NSInteger focusIndex = [super indexAtChartForCoordinate:point];
    
    CGFloat offsetX = point.x - CGRectGetMinX(self.pointRect);
    if (offsetX < self.singleWidth/2) {
        offsetX = 0;
    }
    focusIndex = (offsetX - self.singleWidth/2) / self.singleWidth + 1;//self.singleWidth/2区间
    focusIndex = MAX(MIN(focusIndex, self.endIndex), self.startIndex);
    return focusIndex;
}

- (CGPoint)pointAtChartForIndex:(NSUInteger)index {
    CGPoint point = [super pointAtChartForIndex:index];
    HACLineComponents *lineItem = self.lineDrawingData.firstObject;
    if (lineItem.pointArray && lineItem.pointArray.count > index) {
        point = CGPointFromString(lineItem.pointArray[index]);
    }
    return point;
}

- (HACChartDataEntry*)dataAtChartForIndex:(NSUInteger)focusIndex {
    HACChartDataEntry *indexData = [super dataAtChartForIndex:focusIndex];
    if (self.lineDicData && self.lineDicData.count > 0) {
        NSArray *array = self.lineDicData[@(0)];
        if (array.count > focusIndex) {
            indexData = array[focusIndex];
        }
    }
    return indexData;
}
@end
